package com.devenv.service;

import com.devenv.dto.*;
import com.devenv.entity.User;
import com.devenv.repository.UserRepository;
import com.devenv.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 用户服务类
 * <p>
 * 提供用户相关的核心业务逻辑，包括注册、登录、用户管理等功能
 * </p>
 * 
 * @author DevEnv OpenSource Team
 * @version 1.0.0
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final JwtUtil jwtUtil;
    private final UserStatisticsService userStatisticsService;

    /**
     * 用户注册
     */
    @Transactional
    public UserDTO register(RegisterRequest request) {
        // 验证请求数据
        validateRegisterRequest(request);

        // 验证用户名是否已存在
        if (userRepository.existsByUsername(request.getUsernameLowerCase())) {
            throw new IllegalArgumentException("用户名已存在");
        }

        // 验证邮箱是否已存在
        if (userRepository.existsByEmail(request.getEmailLowerCase())) {
            throw new IllegalArgumentException("邮箱已存在");
        }

        // 创建用户
        User user = new User();
        user.setUsername(request.getUsername());
        user.setEmail(request.getEmail().toLowerCase());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setNickname(request.getFinalNickname());
        user.setLoginType("normal");
        user.setStatus(1);
        user.setRole(User.UserRole.USER);

        user = userRepository.save(user);
        log.info("用户注册成功: username={}, email={}", user.getUsername(), user.getEmail());

        // 初始化用户统计信息
        try {
            userStatisticsService.initializeUserStats(user.getId());
        } catch (Exception e) {
            log.warn("初始化用户统计失败: {}", e.getMessage());
        }

        return convertToDTO(user);
    }

    /**
     * 用户登录
     */
    @Transactional
    public LoginResponse login(LoginRequest request, String clientIp) {
        // 查找用户（支持用户名或邮箱登录）
        User user = findUserForLogin(request.getNormalizedUsername());

        // 检查用户状态
        if (user.getStatus() != 1) {
            throw new IllegalArgumentException("账户已被禁用，请联系管理员");
        }

        // 验证密码
        if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
            log.warn("用户登录密码错误: username={}, ip={}", request.getUsername(), clientIp);
            throw new IllegalArgumentException("用户名或密码错误");
        }

        // 更新登录信息
        updateLoginInfo(user, clientIp);

        // 更新登录统计
        updateLoginStatistics(user.getId());

        // 生成JWT token
        long expiresIn = request.shouldRememberMe() ? 30 * 24 * 60 * 60 * 1000L : 24 * 60 * 60 * 1000L; // 记住登录30天，否则1天
        String token = jwtUtil.generateToken(user.getUsername(), user.getId());
        
        log.info("用户登录成功: username={}, ip={}", user.getUsername(), clientIp);

        return new LoginResponse(token, expiresIn, convertToDTO(user));
    }

    /**
     * 根据用户名获取用户信息
     */
    public UserDTO getUserByUsername(String username) {
        Optional<User> userOpt = userRepository.findByUsername(username);
        if (userOpt.isEmpty()) {
            throw new IllegalArgumentException("用户不存在");
        }
        return convertToDTO(userOpt.get());
    }

    /**
     * 根据用户ID获取用户信息
     */
    public UserDTO getUserById(Long userId) {
        Optional<User> userOpt = userRepository.findById(userId);
        if (userOpt.isEmpty()) {
            throw new IllegalArgumentException("用户不存在");
        }
        return convertToDTO(userOpt.get());
    }

    /**
     * 根据用户ID查找用户实体（内部使用）
     */
    public User findUserById(Long userId) {
        return userRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
    }

    /**
     * 更新用户信息
     */
    @Transactional
    public UserDTO updateUser(Long userId, UserDTO userDTO) {
        User user = findUserById(userId);
        
        // 更新允许修改的字段
        if (userDTO.getNickname() != null) {
            user.setNickname(userDTO.getNickname());
        }
        if (userDTO.getPhone() != null) {
            user.setPhone(userDTO.getPhone());
        }
        if (userDTO.getBio() != null) {
            user.setBio(userDTO.getBio());
        }

        // 重新计算资料完整度
        user.calculateProfileCompletion();
        
        user = userRepository.save(user);
        log.info("用户信息更新成功: userId={}", userId);

        return convertToDTO(user);
    }

    /**
     * 修改密码
     */
    @Transactional
    public void changePassword(String username, String currentPassword, String newPassword) {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));

        // 验证当前密码
        if (!passwordEncoder.matches(currentPassword, user.getPassword())) {
            throw new IllegalArgumentException("当前密码错误");
        }

        // 更新密码
        user.setPassword(passwordEncoder.encode(newPassword));
        userRepository.save(user);

        log.info("用户密码修改成功: username={}", username);
    }

    /**
     * 重置密码（通过邮箱）
     */
    @Transactional
    public void resetPassword(String token, String newPassword, String confirmPassword) {
        // 验证两次密码输入是否一致
        if (!newPassword.equals(confirmPassword)) {
            throw new IllegalArgumentException("两次输入的密码不一致");
        }

        // 查找拥有该令牌的用户
        User user = userRepository.findByPasswordResetToken(token)
                .orElseThrow(() -> new IllegalArgumentException("无效的重置令牌"));

        // 检查令牌是否过期
        if (user.getPasswordResetTokenExpiry() == null || 
            LocalDateTime.now().isAfter(user.getPasswordResetTokenExpiry())) {
            throw new IllegalArgumentException("重置令牌已过期");
        }

        // 更新密码
        user.setPassword(passwordEncoder.encode(newPassword));
        
        // 清除重置令牌
        user.setPasswordResetToken(null);
        user.setPasswordResetTokenExpiry(null);
        
        userRepository.save(user);

        log.info("用户密码重置成功: userId={}", user.getId());
    }

    /**
     * 分页查询用户
     */
    public Page<UserDTO> getUsers(String keyword, Pageable pageable) {
        Page<User> userPage;
        if (keyword != null && !keyword.trim().isEmpty()) {
            userPage = userRepository.findByKeyword(keyword.trim(), pageable);
        } else {
            userPage = userRepository.findAll(pageable);
        }
        return userPage.map(this::convertToDTO);
    }

    /**
     * 获取活跃用户列表
     */
    public List<UserDTO> getActiveUsers(int days) {
        LocalDateTime since = LocalDateTime.now().minusDays(days);
        List<User> activeUsers = userRepository.findRecentActiveUsers(since);
        return activeUsers.stream().map(this::convertToDTO).toList();
    }

    /**
     * 统计用户数量
     */
    public long countUsers() {
        return userRepository.count();
    }

    /**
     * 统计活跃用户数量
     */
    public long countActiveUsers() {
        return userRepository.countActiveUsers();
    }

    /**
     * 验证注册请求
     */
    private void validateRegisterRequest(RegisterRequest request) {
        if (!request.isPasswordMatch()) {
            throw new IllegalArgumentException("两次输入的密码不一致");
        }
    }

    /**
     * 查找用于登录的用户（支持用户名或邮箱）
     */
    private User findUserForLogin(String usernameOrEmail) {
        // 先尝试用户名查找
        Optional<User> userOpt = userRepository.findByUsername(usernameOrEmail);
        if (userOpt.isPresent()) {
            return userOpt.get();
        }

        // 再尝试邮箱查找
        userOpt = userRepository.findByEmail(usernameOrEmail);
        if (userOpt.isPresent()) {
            return userOpt.get();
        }

        throw new IllegalArgumentException("用户名或密码错误");
    }

    /**
     * 更新登录信息
     */
    private void updateLoginInfo(User user, String clientIp) {
        user.setLastLoginTime(LocalDateTime.now());
        user.setLastLoginIp(clientIp);
        user.setLoginCount((user.getLoginCount() == null ? 0 : user.getLoginCount()) + 1);
        user.updateLastActiveTime();
        userRepository.save(user);
    }

    /**
     * 更新登录统计
     */
    private void updateLoginStatistics(Long userId) {
        try {
            userStatisticsService.updateLoginStats(userId, LocalDateTime.now().toLocalDate());
            log.debug("已更新用户{}的登录统计", userId);
        } catch (Exception e) {
            log.warn("更新登录统计失败: {}", e.getMessage());
            // 不影响主流程，继续执行
        }
    }

    /**
     * 转换为DTO
     */
    private UserDTO convertToDTO(User user) {
        UserDTO dto = new UserDTO();
        BeanUtils.copyProperties(user, dto);
        // 不返回敏感信息
        return dto;
    }

    /**
     * 获取用户统计信息
     */
    public UserStats getUserStats() {
        UserStats stats = new UserStats();
        // 这里需要根据实际业务逻辑实现
        stats.setTotalUsers(userRepository.count());
        stats.setActiveUsers(userRepository.count()); // 简化实现
        stats.setNewUsersToday(0L);
        stats.setNewUsersThisWeek(0L);
        stats.setNewUsersThisMonth(0L);
        stats.setAverageActivityScore(0.0);
        return stats;
    }

    /**
     * 用户登出
     */
    public void logout(String token) {
        // 在实际实现中，这里应该将token加入黑名单或清除缓存
        log.info("用户登出，token: {}", token);
    }

    /**
     * 根据token获取当前用户
     */
    public User getCurrentUser(String token) {
        String username = jwtUtil.getUsernameFromToken(token);
        return userRepository.findByUsername(username)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
    }

    /**
     * 根据ID查找用户
     */
    public User findById(Long id) {
        return findUserById(id);
    }

    /**
     * 分页查询所有用户
     */
    public Page<User> findAll(Pageable pageable) {
        return userRepository.findAll(pageable);
    }

    /**
     * 搜索用户
     */
    public Page<User> searchUsers(String keyword, Pageable pageable) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return userRepository.findAll(pageable);
        }
        return userRepository.findByUsernameContainingOrEmailContaining(keyword, keyword, pageable);
    }

    /**
     * 检查用户名是否可用
     */
    public boolean isUsernameAvailable(String username) {
        return !userRepository.existsByUsername(username);
    }

    /**
     * 检查邮箱是否可用
     */
    public boolean isEmailAvailable(String email) {
        return !userRepository.existsByEmail(email);
    }

    /**
     * 激活用户
     */
    public User activateUser(Long id) {
        User user = findUserById(id);
        user.setStatus(1);
        return userRepository.save(user);
    }

    /**
     * 停用用户
     */
    public User deactivateUser(Long id) {
        User user = findUserById(id);
        user.setStatus(0);
        return userRepository.save(user);
    }

    /**
     * 删除用户
     */
    public boolean deleteUser(Long id) {
        if (userRepository.existsById(id)) {
            userRepository.deleteById(id);
            return true;
        }
        return false;
    }

    /**
     * 修改密码 (重载方法，支持用户ID)
     */
    public void changePassword(Long userId, String currentPassword, String newPassword) {
        User user = findUserById(userId);
        changePassword(user.getUsername(), currentPassword, newPassword);
    }
}
